﻿#region Disclaimer/Info
///////////////////////////////////////////////////////////////////////////////////////////////////
// MetaCollection
// 
// MetaCollection is a system to provide a standard structure, permissions and metadata service
// for content organization.
//
// This project is hosted at Google Code at http://code.google.com/p/metacollection/
//
// This project is licensed under the BSD license.  See the License.txt file for more information.
///////////////////////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;

namespace MetaCollection.Framework.Model
{
	/// <summary>
	/// An item relationship allows an item to point to another item within the
	/// collection.
	/// </summary>
	/// <remarks>
	/// The remarks below were rather prescient... The key point is that a Collection
	/// within the MetaCollection is really many Collections therefore for relationships
	/// to work at all they must be a full URI since the GUID is meaningless if you don't
	/// know where to get the GUID request fullfilled.  In addition to the change in
	/// referencing the target item a change was made to recognize that priority is really
	/// a reference to the state associated with the relationship.  With this in mind a
	/// state string was added to allow a ResourceProvider or client to persist additional
	/// information about the context/state of the relationship.  An interesting use of
	/// this might be a relationship pointing to a jabber url where the state is login
	/// information.  If the containing item is a web page it could display an embedded
	/// Jabber client and optionally login. -- Ira Miller 06/19/2009 11:35:13+07:00
	/// 
	/// ------------------------------------------------------------------------------------
	/// It is quite conceivable that we will want to support cross collection references
	/// at some point.  In order to do that we would need to add information to these 
	/// records that indicates the location of the MetaCollection services that can resolve
	/// the TargetItemId.  Since the TargetItemId is a Guid it should be ready for any
	/// wide spread linking that may need to occur.  In the mean time YAGNI so we are 
	/// leaving out the properties for cross collection linking.
	/// -- Ira Miller 05/07/2009 11:40:03+07:00
	/// </remarks>
	public interface IItemRelationship
	{
		/// <summary>
		/// Semantic name that denotes the type of relationship.
		/// </summary>
		/// <example>Requires, IsPartOf, References</example>
		/// <remarks>The relationship type names should be a unique set within a collection</remarks>
		string RelationshipType { get; set; }
		/// <summary>
		/// Item this relationship is pointing to
		/// </summary>
		Uri TargetItem { get; set; }
		/// <summary>
		/// An optional property used to store state information for this relationship.
		/// </summary>
		/// <remarks>
		/// UNDONE: Because state information can very easily become client specific
		/// we should probably come up with a specific/interface for this field so that
		/// multiple clients can determine how to process the data in this field.  
		/// In the mean time we should probably stick with xml.
		/// 
		/// Regardless what is stored in this property and how
		/// it is stored is the exclusive domain of the IProvider registered by the 
		/// IProviderType for this item.
		/// </remarks>
		string State { get; set; }
	}
	/// <summary>
	/// A structure representing an ItemRelationship
	/// </summary>
	[Serializable()]
	public struct ItemRelationship : IItemRelationship
	{
		/// <summary>
		/// Semantic name that denotes the type of relationship.
		/// </summary>
		/// <example>Requires, IsPartOf, References</example>
		/// <remarks>The relationship type names should be a unique set within a collection</remarks>
		public string RelationshipType { get; set; }
		/// <summary>
		/// Item this relationship is pointing to
		/// </summary>
		public Uri TargetItem { get; set; }
		/// <summary>
		/// An optional property used to store state information for this relationship.
		/// </summary>
		public string State { get; set; }
	}

	public static partial class Extensions
	{
		/// <summary>
		/// Converts an enumerable set of IItemRelationship to a simple structure implementation of the interface
		/// </summary>
		/// <param name="relationships"></param>
		/// <returns>An enumerable collection of Item Relationship structures.</returns>
		public static IEnumerable<ItemRelationship> ToStruct(this IEnumerable<IItemRelationship> relationships)
		{
			if (relationships == null)
				yield break;

			foreach (var relation in relationships)
			{
				ItemRelationship itemRelation = new ItemRelationship();
				itemRelation.RelationshipType = relation.RelationshipType;
				itemRelation.State = relation.State;
				itemRelation.TargetItem = relation.TargetItem;
				yield return itemRelation;
			}
			yield break;
		}
	}
}
